
/////////////////////////////////////////////////////////////////////////

package sheep.view;

import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;

import org.jdesktop.animation.timing.Animator;

import org.jdesktop.animation.timing.TimingTarget;
import org.jdesktop.animation.timing.interpolation.PropertySetter;
import org.jdesktop.fuse.InjectedResource;
import org.jdesktop.fuse.ResourceInjector;

import sheep.view.graphics2d.GraphicsUtil;

/////////////////////////////////////////////////////////////////////////

// Ecrean de lancement contient uniquement le logo
public class IntroductionPanel extends JComponent {
  
  /////////////////////////////////////////////////////////////////////////

    ///////////////////////////////////////////////////////////////////////
    // Valeurs du fichiers ressources
    ///////////////////////////////////////////////////////////////////////
    
    // Fond general
    @InjectedResource 
    private LinearGradientPaint backgroundGradient;
    // Image de fond
    @InjectedResource
    private BufferedImage logo;

    // Zone ou l'on dessine le panel
    private final JComponent clip;
    // Valeur pour les fades
    private float fade = 0.0f;
    private float fadeOut = 0.0f;
    // Image pour le fond
    private BufferedImage gradientImage;

    /////////////////////////////////////////////////////////////////////////

    // Constructeur avec la zone de dessin
    IntroductionPanel( final JComponent clip) {
        // Recuperation des valeurs depuis les ressources 
        ResourceInjector.get().inject(this);
        // affectation de la zone de dessin
        this.clip = clip;
    }

    @Override
    // Quand on affiche, on fait un fade in
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible) {
            startFadeIn();
        }
    }

    private void startFadeIn() {
        // On creer un objet animation de type fade de duree 1200 sur le panel courrant
        // Valeur du fade entre 0 et 1
        Animator timer = PropertySetter.createAnimator(1200,this,"fade", 0.0f, 1.0f);
        timer.addTarget(new TimingTarget() {
            @Override
            // Quand on a fini le fade in on lance le fade out
            public void end() {
                startFadeOut();
            }
            @Override
            // Aucune initialisation complementaire
            public void begin() {}
            @Override
            // On ne fait rien à chaque etape
            public void timingEvent(float arg2) {}            
            @Override
            public void repeat() {            	}
        });
        // Configuration du timer
        timer.setAcceleration(0.7f);
        timer.setDeceleration(0.3f);
        // Lancement
        timer.start();
    }

    private void startFadeOut() {
        // On creer un objet animation de type fade out de duree 12000ms sur le panel courrant
        // Valeur du fade entre 0 et 1
        Animator timer = PropertySetter.createAnimator(1200,this,"fadeOut", 0.0f, 1.0f);
        timer.addTarget(new TimingTarget() {
            @Override
            // Quand l'intro est fini on lance le panneau d'attente
            // Dans lequel on charge les donnees
            public void end() {
                TransitionManager.showWaitOverlay();
            }        
            @Override
            // Aucune initialisation complementaire
            public void begin() {}     
            @Override
            // On ne fait rien à chaque etape
            public void timingEvent(float arg2) {}
            @Override
            public void repeat() {}
        });
        // Configuration du timer
        timer.setAcceleration(0.7f);
        timer.setDeceleration(0.3f);
        // Lancement
        timer.start();
    }
    
    // Necessaire aux animators
    public float getFade() {return fade;}
    public void  setFade(float fade) {this.fade  = fade; repaint();}
    public float getFadeOut() {return fadeOut;}
    public void  setFadeOut(float fadeOut) {this.fadeOut  = fadeOut; repaint();}
    
    @Override
    // Effectue le dessin
    protected void paintComponent(Graphics g) {
        // Graphics de fond
        Graphics2D g2 = (Graphics2D) g;
        // Configuration de l'affichage
        setupGraphics(g2);
        // Fond
        paintBackground(g2);
        // Image
        paintLogo(g2);       
    }


    // Configuration de l'affichage
    private static void setupGraphics(Graphics2D g2) {
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
    }

    // Desin de l'mage
    private void paintLogo(Graphics2D g2) {
        // On positionne l'image au centre
        int x = (getWidth() - logo.getWidth()) / 2;
        int y = (getHeight() - logo.getHeight()) / 2;
        // On recupere l'etat des effets courant
        Composite composite = g2.getComposite();
        // On applique une transparence correspondant au fade
        g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, fade));
        // On deeesine l'image
        g2.drawImage(logo, x, y, null);
        // On remets les effets dans leurs etats d'origines
        g2.setComposite(composite);
    }

    // Retourne la zone de clip (desin) utile
    private Rectangle getClipBounds() {
        Point point = clip.getLocation();
        point = SwingUtilities.convertPoint(clip, point, this);
        return new Rectangle(point.x, point.y, clip.getWidth(), clip.getHeight());
    }
    
    // Dessine le fond
    private void paintBackground(Graphics2D g2) {
        // Zone de dessin
        Rectangle rect = getClipBounds();
        // Si l'image de fond n'a pas encore ete cree
        if (gradientImage == null) {
            // On creer une image pour le fond de la taille dessiree
            gradientImage = GraphicsUtil.createCompatibleImage(rect.width, rect.height);
            // On recupere le graphics de l'image
            Graphics2D g2d = (Graphics2D) gradientImage.getGraphics();
            // On applique la painter au graphics
            g2d.setPaint(backgroundGradient);
            // on le rempli effectivement
            g2d.fillRect(0, 0, rect.width, rect.height);
            g2d.dispose();
        }
    }

    /////////////////////////////////////////////////////////////////////////

}

/////////////////////////////////////////////////////////////////////////
